import { Injectable, Module } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import md5 from 'md5';
import { FindAttributeOptions, WhereOptions } from 'sequelize';
import { User } from '../models/user.model';
import { Token } from '../models/token.model';
import { ConfigModule, ConfigService } from '@nestjs/config';

@Injectable()
@Module({
  imports: [ConfigModule]
})
export class UserService {
  constructor(
    private jwtService: JwtService,
    private configService: ConfigService
  ) {}
  // 获取用户信息
  async _getUserInfo(where: WhereOptions<User>, attributes: FindAttributeOptions | null = ['account_id', 'username', 'nickname', 'status']) {
    const opts: { attributes?: FindAttributeOptions } = attributes ? { attributes } : {};
    const ins_user = await User.findOne({ where, ...opts });
    return Promise.resolve(ins_user);
  }
  // 登陆验证
  async _checkUser(username: string, password: string) {
    const password_md5 = md5(password).toUpperCase();
    const ins_user = await this._getUserInfo({ username }, null);
    if (!ins_user) return Promise.reject('用户不存在');
    if (ins_user.password_md5 === password_md5 || password === ins_user.password_md5) {
      if (ins_user.status === 2) return Promise.reject('该账号已冻结，请联系管理员');
      return Promise.resolve(ins_user); // 验证通过
    }
    return Promise.reject('用户名或密码错误');
  }
  async userinfo(account_id: string) {
    const ins_user = await this._getUserInfo({ account_id });
    if (!ins_user) return Promise.reject('用户不存在');
    const result: Record<string, any> = ins_user.toJSON();
    delete result.password_md5;
    return Promise.resolve(result);
  }
  async login(form: { username: string; password: string } & Record<string, any>) {
    const ins_user = await this._checkUser(form.username, form.password);
    const { account_id } = ins_user;
    const _row = await this._token_add({ account_id, userId: ins_user.id, ip: form.ip }, this.configService.get<number>('USER_ONLINE_NUMBER'));
    const { uid } = _row;
    const token = await this.jwtService.signAsync({ account_id, uid });
    return Promise.resolve({ uid, account_id, token });
  }
  async register(form: { username: string; password: string }) {
    const { username, password } = form;
    if (await this._getUserInfo({ username })) {
      return Promise.reject(`该用户名(${username})已被注册`);
    }
    const row: any = { username, password };
    const ins_user = await User.create(row);
    const result: Record<string, any> = ins_user.toJSON();
    delete result.password_md5;
    return Promise.resolve(result);
  }
  async logout(account_id: string) {
    return Token.destroy({ where: { account_id } });
  }

  async _token_get(uid: string, attributes?: FindAttributeOptions) {
    return Token.findOne({ where: { uid }, attributes });
  }

  async _token_del(uid: string) {
    return Token.destroy({ where: { uid } });
  }

  async _token_add(item: any, limit = 5) {
    const rows = await Token.findAll({ where: { account_id: item.account_id }, attributes: ['uid'], order: [['createdAt', 'DESC']], raw: true });
    const uids_valid: string[] = [];
    const uids_failure: string[] = [];
    rows.forEach((row, index) => {
      if (limit > index + 1) {
        uids_valid.push(row.uid);
      } else {
        uids_failure.push(row.uid);
      }
    });
    await Token.destroy({ where: { uid: uids_failure } });
    item = await Token.create(item);
    item = item.toJSON();
    item.uids = [item.uid, ...uids_valid];
    return Promise.resolve(item);
  }
}
